package com.qiangesoft.voice2text.service;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.FormatType;
import com.aliyuncs.http.MethodType;
import com.qiangesoft.voice2text.config.AliyunProperties;
import com.qiangesoft.voice2text.constant.AliyunConstant;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

/**
 * 语音转文字
 *
 * @author qiangesoft
 * @date 2024-04-11
 */
@RequiredArgsConstructor
@Service
public class Voice2TextService {

    private final IAcsClient acsClient;

    private final AliyunProperties aliyunProperties;

    /**
     * 转换
     *
     * @param fileUrl
     * @return
     */
    public JSONArray convert(String fileUrl) {
        // 第一步：提交录音文件识别请求，获取任务ID用于后续的识别结果轮询
        String taskId = this.submitFileTransRequest(aliyunProperties.getAppKey(), fileUrl);
        if (taskId == null) {
            System.out.println("录音文件识别请求失败！");
            return null;
        }

        // 第二步：根据任务ID轮询识别结果
        JSONArray result = this.getFileTransResult(taskId);
        if (result != null) {
            System.out.println("录音文件识别结果查询成功：" + result.toJSONString());
        } else {
            System.out.println("录音文件识别结果查询失败！");
        }
        return result;
    }


    /**
     * 提交识别请求
     *
     * @param appKey
     * @param fileLink
     * @return
     */
    private String submitFileTransRequest(String appKey, String fileLink) {
        // 1.设置请求参数
        CommonRequest postRequest = new CommonRequest();
        postRequest.setSysDomain(aliyunProperties.getDomain());
        postRequest.setSysVersion(AliyunConstant.API_VERSION);
        postRequest.setSysAction(AliyunConstant.POST_REQUEST_ACTION);
        postRequest.setSysProduct(aliyunProperties.getProduct());
        postRequest.setSysMethod(MethodType.POST);
        postRequest.setHttpContentType(FormatType.JSON);

        // 2.设置录音文件参数
        JSONObject taskObject = new JSONObject();
        taskObject.put(AliyunConstant.KEY_APP_KEY, appKey);
        taskObject.put(AliyunConstant.KEY_FILE_LINK, fileLink);
        taskObject.put(AliyunConstant.KEY_VERSION, "4.0");
        taskObject.put(AliyunConstant.KEY_ENABLE_WORDS, true);
        postRequest.putBodyParameter(AliyunConstant.KEY_TASK, taskObject.toJSONString());

        // 3.提交请求返回taskId
        String taskId = null;
        try {
            CommonResponse postResponse = acsClient.getCommonResponse(postRequest);
            if (postResponse.getHttpStatus() == 200) {
                JSONObject result = JSONObject.parseObject(postResponse.getData());
                String statusText = result.getString(AliyunConstant.KEY_STATUS_TEXT);
                if (AliyunConstant.STATUS_SUCCESS.equals(statusText)) {
                    taskId = result.getString(AliyunConstant.KEY_TASK_ID);
                }
            }
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return taskId;
    }

    /**
     * 获取识别结果
     *
     * @param taskId
     * @return
     */
    private JSONArray getFileTransResult(String taskId) {
        // 1.设置任务ID
        CommonRequest getRequest = new CommonRequest();
        getRequest.setSysDomain(aliyunProperties.getDomain());
        getRequest.setSysVersion(AliyunConstant.API_VERSION);
        getRequest.setSysAction(AliyunConstant.GET_REQUEST_ACTION);
        getRequest.setSysProduct(aliyunProperties.getProduct());
        getRequest.putQueryParameter(AliyunConstant.KEY_TASK_ID, taskId);
        getRequest.setSysMethod(MethodType.GET);

        // 2.提交录音文件，以轮询的方式进行识别结果的查询
        JSONArray words = new JSONArray();
        while (true) {
            try {
                CommonResponse getResponse = acsClient.getCommonResponse(getRequest);
                if (getResponse.getHttpStatus() != 200) {
                    break;
                }

                JSONObject rootObj = JSONObject.parseObject(getResponse.getData());
                String statusText = rootObj.getString(AliyunConstant.KEY_STATUS_TEXT);
                if (AliyunConstant.STATUS_RUNNING.equals(statusText) || AliyunConstant.STATUS_QUEUEING.equals(statusText)) {
                    // 继续轮询，注意设置轮询时间间隔
                    Thread.sleep(10000);
                } else {
                    // 状态信息为成功，返回识别结果；状态信息为异常，返回空
                    if (AliyunConstant.STATUS_SUCCESS.equals(statusText)) {
                        JSONObject result = rootObj.getJSONObject(AliyunConstant.KEY_RESULT);
                        if (result != null) {
                            words = result.getJSONArray(AliyunConstant.KEY_WORDS);
                        }
                    }
                    break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return words;
    }
}